﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using JUtil.Extensions;

namespace CodeGen
{
    /// <summary>
    /// 等待解決的問題
    /// (1) 輸出會缺少 asp:  (asp:Panel, asp:GridView, asp:Label, asp:ObjectDataSource)
    /// 
    /// (2) INDENT (期望能夠達到每個屬性都換行)
    /// 
    /// (3) Bind中的括號會被轉換成 &lt;%# Bind(&quot;SINGLE_LIMIT&quot;) %&gt
    /// </summary>
    public class MasterViewAspxFileGenerator
    {
        public MasterViewAspxFileGenerator(string GridViewName,
                                         string TypeName,
                                         string DataObjectTypeName,
                                         List<ColumnInfo> lstColumnInfo)
        {
            this.GridViewName = GridViewName;
            this.TypeName = TypeName;
            this.DataObjectTypeName = DataObjectTypeName;
            this.lstColumnInfo = lstColumnInfo;
        }

        string GridViewName;
        List<ColumnInfo> lstColumnInfo;
        string TypeName;
        string DataObjectTypeName;

        #region GridView Attributes
        private string ID { get { return "grv" + GridViewName; } }
        private string DataSourceID { get { return "ds" + GridViewName; } }
        private string AutoGenerateColumns { get { return "false"; } }
        private string AllowPaging { get { return "true"; } }
        private string PageSize { get { return "10"; } }
        private string OnRowDeleted { get { return ID + "_RowDeleted"; } }
        private string OnPageIndexChanged { get { return ID + "_PageIndexChanged"; } }
        private string OnSelectedIndexChanged { get { return ID + "_SelectedIndexChanged"; } }
        private string OnRowDataBound { get { return ID + "_RowDataBound"; } }
        #endregion

        #region CreateObjectDataSource
        private XmlElement CreateObjectDataSource(XmlDocument doc)
        {
            /*
              <asp:ObjectDataSource 
                ID="dsMaster" 
                runat="server" 
                TypeName="TPPDDB.FestivalTicketSystem.BLL_FESTIVAL_ACTIVITY" 
                DataObjectTypeName="TPPDDB.FestivalTicketSystem.FESTIVAL_ACTIVITY" 
                
                SelectMethod="SelectPaging" 
                InsertMethod="Insert" 
                UpdateMethod="Update"
                DeleteMethod="Delete"
                EnablePaging="True"
             
                SelectCountMethod="SelectCount" 
                OnObjectCreating="dsMaster_ObjectCreating"
                OldValuesParameterFormatString="original_{0}" >
             
                <SelectParameters>
                  <asp:Parameter Name="startRowIndex" Type="Int32" />
                  <asp:Parameter Name="maximumRows" Type="Int32" />
                </SelectParameters>
              </asp:ObjectDataSource> 
             */
            XmlElement ObjectDataSource = doc.CreateElement("asp:ObjectDataSource");

            ObjectDataSource.SetAttribute("ID", DataSourceID);
            ObjectDataSource.SetAttribute("runat", "server");
            ObjectDataSource.SetAttribute("TypeName", TypeName);
            ObjectDataSource.SetAttribute("DataObjectTypeName", DataObjectTypeName);

            ObjectDataSource.SetAttribute("SelectMethod", "SelectPaging");
            ObjectDataSource.SetAttribute("InsertMethod", "Insert");
            ObjectDataSource.SetAttribute("UpdateMethod", "Update");
            ObjectDataSource.SetAttribute("DeleteMethod", "Delete");
            ObjectDataSource.SetAttribute("EnablePaging", "True");

            ObjectDataSource.SetAttribute("SelectCountMethod", "SelectCount");
            ObjectDataSource.SetAttribute("OnObjectCreating", DataSourceID + "_ObjectCreating");
            ObjectDataSource.SetAttribute("OldValuesParameterFormatString", "original_{0}");

            AppendParameters(doc, ObjectDataSource);

            return ObjectDataSource;
        }
        #endregion

        private void AppendParameters(XmlDocument doc, XmlElement ObjectDataSource)
        {
            /*
                <SelectParameters>
                  <asp:Parameter Name="startRowIndex" Type="Int32" />
                  <asp:Parameter Name="maximumRows" Type="Int32" />
                </SelectParameters>
             */
            XmlElement SelectParameters = doc.CreateElement("SelectParameters");

            XmlElement Parameter = null;

            Parameter = doc.CreateElement("asp:Parameter");
            Parameter.SetAttribute("Name", "startRowIndex");
            Parameter.SetAttribute("Type", "Int32");
            SelectParameters.AppendChild(Parameter);

            Parameter = doc.CreateElement("asp:Parameter");
            Parameter.SetAttribute("Name", "maximumRows");
            Parameter.SetAttribute("Type", "Int32");
            SelectParameters.AppendChild(Parameter);

            ObjectDataSource.AppendChild(SelectParameters);
        }

        #region CreateGridView
        private XmlElement CreateGridView(XmlDocument doc)
        {
            XmlElement GridView = doc.CreateElement("asp:GridView");

            GridView.SetAttribute("ID", ID);
            GridView.SetAttribute("DataSourceID", DataSourceID);
            GridView.SetAttribute("AutoGenerateColumns", AutoGenerateColumns);
            GridView.SetAttribute("AllowPaging", AllowPaging);
            GridView.SetAttribute("PageSize", PageSize);

            GridView.SetAttribute("OnRowDeleted", OnRowDeleted);
            GridView.SetAttribute("OnPageIndexChanged", OnPageIndexChanged);
            GridView.SetAttribute("OnSelectedIndexChanged", OnSelectedIndexChanged);
            GridView.SetAttribute("OnRowDataBound", OnRowDataBound);
            GridView.SetAttribute("runat", "server");

            AppendColumns(doc, GridView);

            AppendStyles(doc, GridView);

            AppendPagerSettings(doc, GridView);

            return GridView;
        }
        #endregion

        #region AppendColumns
        private void AppendColumns(XmlDocument doc, XmlElement GridView)
        {
            XmlElement Columns = doc.CreateElement("Columns");

            foreach(ColumnInfo info in lstColumnInfo)
                AppendColumn(doc, Columns, info);

            AppendEditButton(doc, Columns);

            AppendDeleteButton(doc, Columns);

            GridView.AppendChild(Columns);
        }
        #endregion

        #region AppendColumn
        private void AppendColumn(XmlDocument doc, XmlElement Columns, ColumnInfo info)
        {
            XmlElement TemplateField = doc.CreateElement("asp:TemplateField");
            TemplateField.SetAttribute("HeaderText", info.HeaderText);

            XmlElement ItemTemplate = doc.CreateElement("ItemTemplate");

            XmlElement Label = doc.CreateElement("asp:Label");
            Label.SetAttribute("ID", "tf" + info.BindingField);
            Label.SetAttribute("Text", "<%# Bind(\"" + info.BindingField  + "\") %>");
            Label.SetAttribute("runat", "server");

            ItemTemplate.AppendChild(Label);

            TemplateField.AppendChild(ItemTemplate);

            Columns.AppendChild(TemplateField);
        }
        #endregion

        #region AppendEditButton
        private void AppendEditButton(XmlDocument doc, XmlElement Columns)
        {
            XmlElement TemplateField = doc.CreateElement("asp:TemplateField");
            TemplateField.SetAttribute("HeaderText", "修改");

            XmlElement ItemTemplate = doc.CreateElement("ItemTemplate");

            XmlElement Button = doc.CreateElement("Button");
            Button.SetAttribute("ID", "BtnEdit");
            Button.SetAttribute("CommandName", "Select");
            Button.SetAttribute("Text", "修改");
            Button.SetAttribute("runat", "server");

            ItemTemplate.AppendChild(Button);

            TemplateField.AppendChild(ItemTemplate);

            Columns.AppendChild(TemplateField);
        }
        #endregion

        #region AppendDeleteButton
        private void AppendDeleteButton(XmlDocument doc, XmlElement Columns)
        {
            XmlElement TemplateField = doc.CreateElement("asp:TemplateField");
            TemplateField.SetAttribute("HeaderText", "刪除");

            XmlElement ItemTemplate = doc.CreateElement("ItemTemplate");

            XmlElement Button = doc.CreateElement("asp:Button");
            Button.SetAttribute("ID", "BtnDelete");
            Button.SetAttribute("CommandName", "Delete");
            Button.SetAttribute("Text", "刪除");
            Button.SetAttribute("runat", "server");

            ItemTemplate.AppendChild(Button);

            TemplateField.AppendChild(ItemTemplate);

            Columns.AppendChild(TemplateField);
        }
        #endregion

        #region AppendStyles
        private void AppendStyles(XmlDocument doc, XmlElement GridView)
        {
            /*
              <PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" />
              <SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" />
              <HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
              <EditRowStyle BackColor="#999999" />
              <AlternatingRowStyle BackColor="White" ForeColor="#006600" />
             */
            XmlElement PagerStyle = doc.CreateElement("PagerStyle");
            PagerStyle.SetAttribute("BackColor", "#284775");
            PagerStyle.SetAttribute("ForeColor", "White");
            PagerStyle.SetAttribute("HorizontalAlign", "Center");
            GridView.AppendChild(PagerStyle);

            XmlElement SelectedRowStyle = doc.CreateElement("SelectedRowStyle");
            SelectedRowStyle.SetAttribute("BackColor", "#E2DED6");
            SelectedRowStyle.SetAttribute("Font-Bold", "True");
            SelectedRowStyle.SetAttribute("ForeColor", "#333333");
            GridView.AppendChild(SelectedRowStyle);

            XmlElement HeaderStyle = doc.CreateElement("HeaderStyle");
            HeaderStyle.SetAttribute("BackColor", "#5D7B9D");
            HeaderStyle.SetAttribute("Font-Bold", "True");
            HeaderStyle.SetAttribute("ForeColor", "White");
            GridView.AppendChild(HeaderStyle);

            XmlElement EditRowStyle = doc.CreateElement("EditRowStyle");
            EditRowStyle.SetAttribute("BackColor", "#999999");
            GridView.AppendChild(EditRowStyle);

            XmlElement AlternatingRowStyle = doc.CreateElement("AlternatingRowStyle");
            AlternatingRowStyle.SetAttribute("BackColor", "White");
            AlternatingRowStyle.SetAttribute("ForeColor", "#006600");
            GridView.AppendChild(AlternatingRowStyle);
        }
        #endregion

        #region AppendPagerSettings
        private void AppendPagerSettings(XmlDocument doc, XmlElement GridView)
        {
            /*
              <PagerSettings 
                FirstPageText="第一頁" 
                LastPageText="最末頁" 
                Mode="NumericFirstLast" 
                Position="Bottom" />
             */
            XmlElement PagerSettings = doc.CreateElement("PagerSettings");
            PagerSettings.SetAttribute("FirstPageText", "第一頁");
            PagerSettings.SetAttribute("LastPageText", "最末頁");
            PagerSettings.SetAttribute("Mode", "NumericFirstLast");
            PagerSettings.SetAttribute("Position", "Bottom");
            GridView.AppendChild(PagerSettings);
        }
        #endregion

        public void Export(string filepath)
        {
            XmlDocument doc = new XmlDocument();

            XmlElement Panel = doc.CreateElement("asp:Panel");
            Panel.SetAttribute("ID", "pnlData");
            Panel.SetAttribute("runat", "server");

            XmlElement GridView = CreateGridView(doc);
            Panel.AppendChild(GridView);

            XmlElement ObjectDataSource = CreateObjectDataSource(doc);
            Panel.AppendChild(ObjectDataSource);

            doc.AppendChild(Panel);

            doc.Save(filepath);

            string buffer = System.IO.File.ReadAllText(filepath);

            buffer = ExecuteReplace(buffer);

            JUtil.Path.File.Delete(filepath);

            buffer.SaveAs(filepath);
        }

        private string ExecuteReplace(string buffer)
        {
            buffer = ReplaceTag(buffer);
            buffer = ReplaceBrackets(buffer);
            buffer = ReplaceQuote(buffer);
            return buffer;
        }

        private string ReplaceBrackets(string buffer)
        {
            buffer = buffer.Replace("&lt;", "<");
            buffer = buffer.Replace("&gt;", ">");
            return buffer;
        }

        private string ReplaceQuote(string buffer)
        {
            buffer = buffer.Replace("&quot;", "'");
            return buffer;
        }
        private string ReplaceTag(string buffer)
        {
            string[] replacements = 
            { 
                "Panel",
                "GridView",
                "TemplateField",
                "Label",
                "Button",
                "ObjectDataSource"
            };

            foreach (string item in replacements)
            {
                buffer = buffer.Replace(item, "asp:" + item);
            }

            // 特殊處理 <Parameter
            buffer = buffer.Replace("<Parameter", "<asp:Parameter");

            return buffer;
        }
    }

    public class ColumnInfo
    {
        public string HeaderText;
        public string BindingField;
    }
}
